package org.funtester.performance.books.chapter04.section2;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class HttpRequestTool {

    /**
     * 构建 GET 请求
     * @param uri
     * @return
     */
    public static HttpGet getHttpGet(String uri) {
        return new HttpGet(uri);
    }

    /**
     * 构建 GET 请求
     * @param uri
     * @param params
     * @return
     */
    public static HttpGet getHttpGet(String uri, JSONObject params) {
        String paramsStr = convertParams(params);// 将参数转换为 GET 请求参数字符串
        HttpGet httpGet = new HttpGet(uri + paramsStr);// 构建 GET 请求
        return httpGet;
    }

    /**
     * 构建 POST 请求
     * @param uri
     * @return
     */
    public static HttpPost getHttpPost(String uri) {
        return new HttpPost(uri);// 构建 POST 请求
    }

    /**
     * 构建 POST 请求,文本参数
     * @param uri
     * @param params
     * @return
     */
    public static HttpPost getHttpPost(String uri, String params) {
        HttpPost httpPost = new HttpPost(uri);// 构建 POST 请求
        StringEntity stringEntity = new StringEntity(params, HttpClientTool.DEFAULT_CHARSET);// 构建请求体
        httpPost.setEntity(stringEntity);// 设置请求体
        httpPost.addHeader("Content-Type", "application/json");// 设置请求头
        return httpPost;
    }

    /**
     * 构建 POST 请求,表单参数
     * @param uri
     * @param params
     * @return
     */
    public static HttpPost getHttpPost(String uri, JSONObject params) {
        HttpPost httpPost = new HttpPost(uri);// 构建 POST 请求
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        Set<String> keySet = params.keySet();// 获取所有参数名
        for (String key : keySet) {// 遍历所有参数名
            String value = params.getString(key);// 获取参数值
            formparams.add(new BasicNameValuePair(key, value));// 构建表单参数
        }
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, HttpClientTool.DEFAULT_CHARSET);// 构建请求体
        httpPost.setEntity(entity);// 设置请求体
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");// 设置请求头
        return httpPost;
    }

    /**
     * 构建 POST 请求,文件参数
     * @param uri
     * @param params
     * @param fileKey 文件参数的参数名
     * @param filePath 文件参数的文件路径
     * @return
     */
    public static HttpPost getHttpPost(String uri, JSONObject params, String fileKey, String filePath) {
        HttpPost httpPost = new HttpPost(uri);// 构建 POST 请求
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(filePath);
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在");
        }
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();// 新建MultipartEntityBuilder对象
        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            String value = params.getString(key);
            StringBody body = new StringBody(value, ContentType.create("text/plain", HttpClientTool.DEFAULT_CHARSET));// 设置文本参数
            builder.addPart(key, body);
        }
        builder.addBinaryBody(fileKey, inputStream, ContentType.create("multipart/form-data"), filePath);// 设置文件参数
        HttpEntity entity = builder.build();
        httpPost.setEntity(entity);
        httpPost.addHeader("Content-Type", "multipart/form-data");// 设置请求头
        return httpPost;
    }

    /**
     * 获取所有响应头信息
     * @param message
     * @return
     */
    public static List<JSONObject> getAllHeaders(HttpMessage message) {
        Header[] headers = message.getAllHeaders();
        List<JSONObject> headerList = new ArrayList<>();
        for (Header header : headers) {
            headerList.add(new JSONObject()// 构建 JSON 对象
                    .fluentPut(header.getName(), header.getValue()));// 设置响应头名和响应头值
        }
        return headerList;
    }

    /**
     * 解析响应,返回响应字符串
     * @param response
     * @return
     */
    public static String parseReponseString(CloseableHttpResponse response) {
        HttpEntity entity = response.getEntity();// 获取响应实体
        String responseStr = null;
        try {
            responseStr = EntityUtils.toString(entity);// 获取响应实体内容
            EntityUtils.consume(entity);// 关闭响应实体
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseStr;
    }

    /**
     * 解析响应,返回响应 JSON 对象
     * @param response
     * @return
     */
    public static JSONObject parseReponseJson(CloseableHttpResponse response) {
        String responseStr = parseReponseString(response);// 解析响应
        if (responseStr != null && !responseStr.isEmpty()) {// 响应不为空
            return JSONObject.parseObject(responseStr);// 解析响应为 JSON 对象
        } else {
            return new JSONObject();// 响应为空,返回空 JSON 对象
        }
    }

    /**
     * 将参数转换为 GET 请求参数字符串
     * @param params
     * @return
     */
    public static String convertParams(JSONObject params) {
        if (params == null || params.isEmpty()) {// 没有参数,返回空字符串
            return "";
        }
        StringBuilder result = new StringBuilder("?");// 有参数,返回?开头的字符串
        boolean first = true;// 是否是第一个参数
        Set<String> keySet = params.keySet();// 获取所有参数名
        for (String key : keySet) {// 遍历所有参数名
            String value = params.getString(key);// 获取参数值
            if (first) {// 第一个参数前面不加&
                first = false;
            } else {
                result.append("&");// 第二个参数开始,每个参数前面加&
            }
            try {
                result.append(URLEncoder.encode(key, HttpClientTool.DEFAULT_CHARSET.name()))// 拼接参数名编码
                        .append("=")// 拼接参数名和参数值之间加=
                        .append(URLEncoder.encode(value, HttpClientTool.DEFAULT_CHARSET.name()));// 拼接参数值编码
            } catch (UnsupportedEncodingException e) {// 不支持的编码异常
                e.printStackTrace();
            }
        }
        return result.toString();// 返回拼接好的字符串
    }

}
